package com.jh.track.gateway.filter;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.jh.track.common.core.constant.AuthConstants;
import com.jh.track.common.core.result.ResultCode;
import com.jh.track.gateway.util.WebUtils;
import com.nimbusds.jose.JWSObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.HttpMethod;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.util.UriComponentsBuilder;
import reactor.core.publisher.Mono;

import java.net.URI;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;

/**
 * @author ：xy
 * @date ：Created in 2021/4/17 17:57
 * @description：将登录用户的JWT转化成用户信息的全局过滤器
 * @version: v 1.0.0
 * @email: xy100826@163.com
 */
@Component
@Slf4j
public class AuthGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private RedisTemplate redisTemplate;
    private final static String DEFAULT_FILTER_PATH = "/ws/";

    @SneakyThrows
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
            // 非JWT或者JWT为空不作处理
            String token = request.getHeaders().getFirst(AuthConstants.AUTHORIZATION_KEY);
            if (StrUtil.isBlank(token) || !token.startsWith(AuthConstants.AUTHORIZATION_PREFIX)) {
                return chain.filter(exchange);
            }
            // 解析JWT获取jti，以jti为key判断redis的黑名单列表是否存在，存在拦截响应token失效
            token = token.replace(AuthConstants.AUTHORIZATION_PREFIX, Strings.EMPTY);
            JWSObject jwsObject = JWSObject.parse(token);
            String payload = jwsObject.getPayload().toString();
            JSONObject jsonObject = JSONUtil.parseObj(payload);
            String jti = jsonObject.getStr(AuthConstants.JWT_JTI);
            Boolean isBlack = redisTemplate.hasKey(AuthConstants.TOKEN_BLACKLIST_PREFIX + jti);
            if (isBlack) {
                return WebUtils.writeFailedToResponse(response, ResultCode.TOKEN_ACCESS_FORBIDDEN);
            }

            // 存在token且不是黑名单，request写入JWT的载体信息
            request = exchange.getRequest().mutate()
                    .header(AuthConstants.JWT_PAYLOAD_KEY, payload)
                    .build();
            exchange = exchange.mutate().request(request).build();
            return chain.filter(exchange);
    }


    @Override
    public int getOrder() {
        return 0;
    }

    private static String convertWsToHttp(String scheme) {
        scheme = scheme.toLowerCase();
        return "ws".equals(scheme) ? "http" : "wss".equals(scheme) ? "https" : scheme;
    }
}